block1 ブロックチェーンとかよくわからなくても大丈夫!Node.js で Ethereum のウォレット作成・暗号通貨の送金・ NFT の所有権確認をやってみよう!
はじめに
ブロックチェーンとかよくわからなくても、ブロックチェーンを利用するプログラムを書くことはできます!
ブロックチェーンがどのように動くかを真面目に勉強をするのも奥が深くて面白いですが、とりあえずウォレットの作成・暗号通貨の送金・NFT の所有権確認をやってみましょう。
実際ぼくも本当はブロックチェーンとかよくわかっていないですが、なんとか動くものは作れています:P
前提
とりあえず Node.js が動けば ok!
JavaScript ちょっとわかれば ok!
事前準備をやっていない人むけ
Node.js が動く環境がない人は以下を参考に Node.js をインストールしてみてください。
作業用ディレクトリの作成
ホームディレクトリ以下に web3tokyo/0 ディレクトリを作成して作業を進めます。
code:bash
mkdir -p web3tokyo/0
cd web3tokyo/0
ethers.js のインストール
Ethereum ブロックチェーンのプログラムをいいかんじに書くことを可能にする便利なライブラリである ethers.js をインストールします。 code:bash
npm i --save ethers
Ethereum のウォレットをつくる!
Ethereum ブロックチェーン上の通貨 Ether や NFT 等を保持したり、移動指示を出すための「ウォレット」を作成します。
プログラム
以下のプログラムを書いて実行すると、ウォレットが生成されます。
code:createWallet.js
// createWallet.js
(async () => {
// ethers.js をインポート
const ethers = require('ethers')
// ウォレットを生成
const wallet = new ethers.Wallet.createRandom()
// ウォレットのアドレスを取得
const address = wallet.address
console.log('address:', address)
// ウォレットの秘密鍵を取得
const privateKey = wallet.privateKey
console.log('privateKey:', privateKey)
// ウォレットのニーモニックを取得
const mnemonic = wallet.mnemonic.phrase
console.log('mnemonic:', mnemonic)
})()
上記コードの実行
code:bash
node createWallet.js
出力例
address: 0x44D991659cC4a8433A667592009438A9F9a906ee
privateKey: 0x9fcf22b9aaf2b8e1000c0ca4cadde61c1b197fc0b402930028338b634fce1d91
mnemonic: quote actual kiss swim inhale hamster bind taxi rather trick tube prison
注意
!!! ここで出力された address, mnemonic, privateKey は後ほど利用するので、1Password 等で保存しておいてください !!!
!!! mnemonic と privateKey は第三者に見られないようにしてください !!!
アドレスとは
アドレス(address)は銀行の口座番号のようなものです。暗号通貨や NFT を送付するときに宛先として指定します。
アドレスは Ethereum ブロックチェーン上でユニークであり、アカウント ID でもあります。
秘密鍵とは
秘密鍵(privateKey)は Ethereum ウォレットそのものです。
したがって秘密鍵を奪われることはウォレット内の資産すべてを奪われることになります。
楕円曲線を使った公開鍵暗号の秘密鍵に該当します。
一方、アドレスは公開鍵暗号の公開鍵から導出された値です。
Ethereum ブロックチェーンにおける Ether の送金や NFT の移動等のトランザクションは、この秘密鍵によるデジタル署名によって実現されています。
ニーモニックとは
秘密鍵を人間が覚えやすいように英単語の羅列にしたものです。
秘密鍵と同様、 Ethereum ウォレットそのものです。
したがってニーモニックを奪われることはウォレット内の資産すべてを奪われることになります。
暗号通貨を送金してみよう!
ウォレットを作ることができたので、さっそく暗号通貨 Ether を送金してみましょう。
その前に、自分のウォレットの残高を確認してみましょう。
ウォレットの残高確認
例: 0xA632f917bC8AcF34b547372715e9d846aF1A28b7 というアドレスの残高を確認
送金してみよう
当たり前ですが、ウォレットを作ったばかりなので、ウォレットの残高は 0 だったはずです。
Ethereum には「テストネット」というテスト・開発用のブロックチェーンがあります。
テスト用の Ether を取得したり、送金のテストを行うことができるやつです。
でも、やっぱり本物の Ether を使ったほうが面白いです。
0.0042 Ether を配布するので、以下に先ほど作成したアドレスと名前を列挙してください。
code:addresses
アドレス, 名前, 送金済?
0xA632f917bC8AcF34b547372715e9d846aF1A28b7, piyo.eth, false
0xf796a7835C3809cC1013d0094Baf897478a32f9a, 堤, true
0x8c9220F7477D7990351611813b457b207d046D65,岡本,true
0x3Cc827A8d96f4BaCd00c6D9258D8144bdec681EA,塚田,true
0xE5625fC059AeBD96c12B3D67Dd6A3A9DbA7db11b, Toshiki, true
0x6aa083CA62f6aBc2145a0903DbCdeCB12aD8654a,樋口,true
0x197572C16bE19107be7B1224811C2F839894D7E6,鈴木,true
0x25a702DA93881520d6772150717c8c4296Ce5Aa2,畑,true
0x98e539A6517883c2ca31B9EB54c80ceedd57f5f1,金,true
自分のウォレット残高を確認
Ether を受け取ったら Etherscan で自分のウォレットの残高を再度確認してみましょう。 Ether を受け取れていることを確認したら、早速 Ether を送金してみましょう。
プログラム
以下のプログラムを書いて実行すると、Ether を送金することができます。
次の部分を書き換えて、送金を試してください。
PRIVATE_KEY: 先ほど生成した自分のウォレットの秘密鍵
TO: 隣に座っている人のアドレス
code:sendEther.js
// sendEther.js
// 秘密鍵
const PRIVATE_KEY = 'REPLACE_ME';
// Ether 送金先のアドレス
const TO = 'REPLACE_ME';
// ethers.js をインポート
const ethers = require('ethers')
// ブロックチェーンノードの JSON RPC プロバイダ
const provider = ethers.getDefaultProvider()
// 秘密鍵からウォレットを生成
// 同時にプロバイダに接続し、ブロックチェーンへのトランザクション送信を可能に
const wallet = new ethers.Wallet(PRIVATE_KEY, provider)
// ウォレットのアドレスを取得
const address = wallet.address
console.log('address:', address)
// 0.001 Ether を TO に送金するトランザクションをブロックチェーンに送信
wallet.sendTransaction({
to: TO,
value: ethers.utils.parseEther('0.001')
})
上記コードの実行
code:bash
node sendEther.js
NFT の所有権確認をやってみよう!
ある特定の NFT がどのウォレットに所有されているかをプログラムで確認してみましょう。
NFT の所有権はブロックチェーン上のデータとして記録されています。
つまり、NFT の所有権を確認するということは、ブロックチェーン上のデータを確認するということになります。
NFT の所有権を確認できると、例えば、ある NFT を持っている人だけに特定のサービスを提供する等、ブロックチェーンと連携したアプリケーションを作ることができます。
ある特定の NFT を持っている人だけが開けることのできるスマートロックの例(ステマ!)
NFT の実体
NFT の実体はブロックチェーン上にデプロイされた「スマートコントラクト」(プログラム)です。
スマートコントラクトはウォレットと同じく、 Ethereum ブロックチェーン上でユニークな ID を持ちます。
これを「コントラクトアドレス」と呼びます。
一般に 1 つのスマートコントラクトは複数の NFT を持ちます。
同一スマートコントラクト以下の NFT を全てまとめて「NFT コレクション」と呼びます。
各々の NFT は「トークン ID」というユニークな ID を持ちます。
N 個の NFT を持つ NFT コレクションの例
code:text
NFT Collection (Smart Contract)
├ NFT tokenId 1
├ NFT tokenId 2
├ NFT tokenId 3
...
└ NFT tokenId N
今回所有権を確認する NFT
OpenSea の URL フォーマット
ちなみに、OpenSea の URL のフォーマットは次にようになっています。
code:text
NFT の所有権を確認する方法
NFT の実体であるスマートコントラクトは、 ブロックチェーン上にデプロイされたプログラムです。
スマートコントラクトには関数やプロパティを実装することができます。
ownerOf 関数
ERC-721 に準拠した NFT スマートコントラクトは ownerOf(tokenId) という関数を持っています。 引数に渡した tokenId の NFT の所有者を返す関数です。
今回はこの ownerOf(tokenId) という関数を使って、NFT の所有者を確認をします。
今回所有権を確認する NFT
BlueBirds.eth NFT コレクションのコントラクトアドレス: 0x778efc5961570158df0989ad7c9369ca23383adc トークン ID: 1
プログラム
以下のプログラムを書いて実行すると、 BlueBirds.eth NFT コレクションの tokenId 1 の所有者のアドレスを取得することができます。 code:getNftOwner.js
// getNftOwner.js
(async () => {
// BlueBirds.eth のコントラクトアドレス
const NFT_CONTRACT_ADDRESS = '0x778efc5961570158df0989ad7c9369ca23383adc'
// 所有権を確認したい NFT の tokenId
const NFT_TOKEN_ID = '1'
// ethers.js をインポート
const ethers = require('ethers')
// スマートコントラクトはバイナリとしてブロックチェーン上にデプロイされているため関数シグネチャが必要
// どんな関数か、引数の型、戻り値の型など
// ここでは ownerOf 以外の関数は削ってあります
const NFT_CONTRACT_ABI = [{
"name":"ownerOf",
"stateMutability":"view","type":"function"
}]
// ブロックチェーンノードの JSON RPC プロバイダ
const provider = new ethers.providers.getDefaultProvider()
// NFT コントラクトのインスタンス
const contract = new ethers.Contract(NFT_CONTRACT_ADDRESS, NFT_CONTRACT_ABI, provider)
// NFT コントラクトの ownerOf 関数を呼び、NFT 所有者のアドレスを返す
const address = await contract.ownerOf(NFT_TOKEN_ID)
console.log(address)
})()
上記コードの実行
code:bash
node getNftOwner.js
おわりに
Ethereum 自体はよくわからなくても Ethereum と連携したアプリを作ることはできるので、ぜひいろいろチャレンジしてみてください!
おまけ
自分が所有する NFT のトークン ID を確認してみましょう。
code:url
上記コードを書き換えて、配布された NFT の 所有者のアドレスをプログラムから確認してみましょう。
code:adderss
address, name, isMinted
0x3Cc827A8d96f4BaCd00c6D9258D8144bdec681EA, shin, true
0xE5625fC059AeBD96c12B3D67Dd6A3A9DbA7db11b, toshiki, true
0x6aa083CA62f6aBc2145a0903DbCdeCB12aD8654a,true
0x25a702DA93881520d6772150717c8c4296Ce5Aa2,true
0xf796a7835C3809cC1013d0094Baf897478a32f9a, true
0x8c9220F7477D7990351611813b457b207d046D65,岡本,true
0x98e539A6517883c2ca31B9EB54c80ceedd57f5f1,金,
Next